#include "LPC13xx.h"
#include "usb.h"
#include "usbcfg.h"
#include "usbhw.h"
#include "usbcore.h"
#include "vendor.h"

#include "gpio.h"

int nPortNumberTwo = 2;
int nLedPosition4 = 4;
int nLedPosition5 = 5;
int nLedPosition6 = 6;
int nLedPosition7 = 7;
int f_nUserButton = 9;
int f_nGpioPortNumberOne = 1;
int f_nWakeUpButton = 4;

int nDirectionOut = 1;
int f_nDirectionIn = 0;

int nTurnLedOn = 0;

int f_nLedOneState = 0;
int f_nLedTwoState = 0;


#define MINIMUM_LED_NUMBER 0
#define MAXIMUM_LED_NUMBER 7
#define ERROR_LED_NUMBER_UNDER_MINIMUM -2
#define ERROR_LED_NUMBER_OVER_MAXIMUM -3

#define LED0_NUMBER 0
#define LED1_NUMBER 1
#define LED2_NUMBER 2
#define LED3_NUMBER 3
#define LED4_NUMBER 4
#define LED5_NUMBER 5
#define LED6_NUMBER 6
#define LED7_NUMBER 7

#define TURN_LED_ON 0
#define TURN_LED_OFF 1

int SetLed0(int nState) {
	GPIOSetValue(PORT3, LED0_NUMBER, nState);
}
int SetLed1(int nState) {
	GPIOSetValue(PORT3, LED1_NUMBER, nState);
}
int SetLed2(int nState) {
	GPIOSetValue(PORT3, LED2_NUMBER, nState);
}
int SetLed3(int nState) {
	GPIOSetValue(PORT3, LED3_NUMBER, nState);
}
int SetLed4(int nState) {
	GPIOSetValue(PORT2, LED4_NUMBER, nState);
}
int SetLed5(int nState) {
	GPIOSetValue(PORT2, LED5_NUMBER, nState);
}
int SetLed6(int nState) {
	GPIOSetValue(PORT2, LED6_NUMBER, nState);
}
int SetLed7(int nState) {
	GPIOSetValue(PORT2, LED7_NUMBER, nState);
}


/**
 * SetLed
 * @param nLedNumber - Led number 0-7
 * @param nStat - 0 = On, 1 = Off.
 * @return 0 = ok, otherwise error.
 */
int SetLed(int nLedNumber, int nState) {
	int nReturnCode = -1;
	if (nLedNumber <  MINIMUM_LED_NUMBER ) {
		nReturnCode = ERROR_LED_NUMBER_UNDER_MINIMUM;
	} else if ( nLedNumber > MAXIMUM_LED_NUMBER) {
		nReturnCode = ERROR_LED_NUMBER_OVER_MAXIMUM;
	}

	switch (nLedNumber) {
		case 0:
			SetLed0(nState);
			nReturnCode = 0;
			break;
		case 1:
			SetLed1(nState);
			nReturnCode = 0;
			break;
		case 2:
			SetLed2(nState);
			nReturnCode = 0;
			break;
		case 3:
			SetLed3(nState);
			nReturnCode = 0;
			break;
		case 4:
			SetLed4(nState);
			nReturnCode = 0;
			break;
		case 5:
			SetLed5(nState);
			nReturnCode = 0;
			break;
		case 6:
			SetLed6(nState);
			nReturnCode = 0;
			break;
		case 7:
			SetLed7(nState);
			nReturnCode = 0;
			break;
	} // end switch.
	return(nReturnCode);
}

void InitializeGpioPortDirections() {
	GPIOSetDir(PORT3, LED0_NUMBER, nDirectionOut);
	GPIOSetDir(PORT3, LED1_NUMBER, nDirectionOut);
	GPIOSetDir(PORT3, LED2_NUMBER, nDirectionOut);
	GPIOSetDir(PORT3, LED3_NUMBER, nDirectionOut);
	GPIOSetDir(PORT2, LED4_NUMBER, nDirectionOut);
	GPIOSetDir(PORT2, LED5_NUMBER, nDirectionOut);
	GPIOSetDir(PORT2, LED6_NUMBER, nDirectionOut);
	GPIOSetDir(PORT2, LED7_NUMBER, nDirectionOut);

}
/**
 *
 */
void ToggleLed(nButtonValue) {

	GPIOSetValue(nPortNumberTwo, nLedPosition4, nTurnLedOn);

	if (nButtonValue == 1) {
		f_nLedOneState++;
		if ( f_nLedOneState > 1) {
			f_nLedOneState = 0;
		}
		GPIOSetValue(nPortNumberTwo, nLedPosition5, f_nLedOneState);

	}
	if (nButtonValue == 2) {
		f_nLedTwoState++;
		if ( f_nLedTwoState > 1) {
			f_nLedTwoState = 0;
		}
		GPIOSetValue(nPortNumberTwo, nLedPosition6, f_nLedTwoState);

	}
}


uint8_t GetButtonState() {
	uint8_t nReturnValue=0;

	uint32_t nButtonUser = LPC_GPIO2->DATA & (1<<9);
	uint32_t nButtonWakeUp = LPC_GPIO1->DATA & (1<<4);

	if (!nButtonUser) {
		nReturnValue|=1;
	}
	if (!nButtonWakeUp) {
		nReturnValue|=2;
	}
	return(nReturnValue);
}

int main(void) {
	uint8_t nButonState = 0;
	uint8_t  nTemp= 0;

	SystemInit();

	InitializeGpioPortDirections();

	USBIOClkConfig();
	USB_Init();
	USB_Connect(TRUE);
	while (!USB_Configuration)
		;


	SetLed(1, TURN_LED_ON);

	init_timer32(0, 0xFFFF);
	enable_timer32(0);

	int nIndex = 0;
	for (nIndex = MINIMUM_LED_NUMBER; nIndex <= MAXIMUM_LED_NUMBER; nIndex++) {
		SetLed(nIndex, TURN_LED_ON);
		delay32Ms(0,1000);
	}
	//GPIOInit();

	SetLed(1, TURN_LED_OFF);

	// Set USER button as input.
	GPIOSetDir(nPortNumberTwo, f_nUserButton, f_nDirectionIn);
	GPIOSetDir(f_nGpioPortNumberOne, f_nWakeUpButton, f_nDirectionIn);

	nButonState = nTemp = GetButtonState();

	// This is IN, and it is in relations to the host, to IN here is what is going to the host.
	USB_WriteEP(0x81, &nTemp, 1);

	// GPIOSetInterrupt(nPortNumberTwo, f_nUserButton, );


	// GPIOInit();
	while (1) {
		nTemp = GetButtonState();
		if ( nButonState != nTemp) {
			USB_WriteEP(0x81, &nTemp, 1);
			ToggleLed(nTemp);
		}
		nButonState = nTemp;
	}
}
